package single;

/**
 * questions:
 * 1 什么时候要用单例模式
 *      无状态的工具类
 *      - Windows的TaskManager(任务管理器)就是很的单例模式。我们是不能打开两个windowstaskmanager。
 *      - windows的RecycleBin(回收站)也是的单例应用。在整个系统运行过程中，回收站一直维护着仅有的一个实例。
 *      - 网站的计数器，通常采用单例模式实现，否则难以同步。
 *
 * 2 有哪几种实现方式
 *      - 饿汉式
 *      - 懒汉式
 *
 * 3 单例模式有几个特点
 *      - private 初始化方法
 *      - private static 变量
 *      - 如果是饿汉式实现, 需要 volatile 修饰，防止创建对象时线程重排序导致混乱
 *      - 双重检查锁 --> if (... == null) 里面 synchronized { if (... == null)}
 */
// 饿汉式
public class SingleMode {

    private static SingleMode singleton = new SingleMode();

    private SingleMode() {

    }

    public static SingleMode getInstance() {
        return singleton;
    }

}

// 懒汉式 - 线程不安全
class LazySingleMode2 {
    private static LazySingleMode2 singleton = null;

    public static LazySingleMode2 getInstance() {
        if (null == singleton) {
            singleton = new LazySingleMode2();
        }
        return singleton;
    }
}

// 懒汉式 - 线程安全
// 关键代码: volatile 修饰变量, synchronized 代码块
class LazySingleMode {
    private volatile static LazySingleMode singleton = null;

    public static LazySingleMode getInstance() {
        if (null == singleton){
            synchronized (LazySingleMode.class) {
                if (null == singleton) {
                    singleton = new LazySingleMode();
                }
            }
        }
        return singleton;
    }
}

/**
 * 枚举
 *
 * 我还没弄明白...
 *
 * 放上 菜鸟教程 里的原文:
 * 这种实现方式还没有被广泛采用，但这是实现单例模式的最佳方法。它更简洁，自动支持序列化机制，绝对防止多次实例化。
 * 这种方式是 Effective Java 作者 Josh Bloch 提倡的方式，它不仅能避免多线程同步问题，而且还自动支持序列化机制，防止反序列化重新创建新的对象，绝对防止多次实例化。
 */
enum EnumSingleton {
    INSTANCE;
    public void whateverMethod() {
    }
}